﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using IMCOM.Imagiality.Core;
using IMCOM.Imagiality.ImageProcessing.Canvas2D.Commands;
using IMCOM.Imagiality.ImageProcessing.Canvas2D.AutoContrast;
using IMCOM.Imagiality.ImageProcessing.Canvas2D.ROI;

namespace IMCOM.Imagiality.ImageProcessing.Canvas2D
{
    public class Canvas2DImageProcessor : ImageProcessor, Canvas2DImageEventListener
    {
        
        private Canvas2DROIState roiState;
        private CanvasImageWrapper canvasImageWrapper;
        private Canvas2DGUI canvas2DGUI;
        private bool isGuiOpened;


        public Canvas2DImageProcessor(Canvas2DGUI gui)
        {
            canvas2DGUI = gui;
            isGuiOpened = true;
        }

        public Canvas2DImageProcessor()
        {
            isGuiOpened = false;  
            roiState = new ROI.FirstPointSelection(this);

        }

        public GenericImage getProcessedImage(GenericImage input)
        {
            IList<GenericImage> inputAsList = new List<GenericImage>();
            inputAsList.Add(input);
            GenericImage outputAsSingleGenericImage = getProcessedImages(inputAsList)[0];
            return outputAsSingleGenericImage;
        }

        public IList<GenericImage> getProcessedImages(IList<GenericImage> input)
        {
            // if GUI is already opened, wait for the completion signal
            if (isGuiOpened)
            {
                lock (this)
                {
                    Monitor.Wait(this);
                }
            }
            // else, open the GUI and wait for it to be closed
            else 
            {
                // değişecek
                canvasImageWrapper = new CanvasImageWrapper(input);
                canvas2DGUI = new Canvas2DGUI(canvasImageWrapper);
                canvas2DGUI.ImageEventListener = this;
 
                Form guiForm = new Form();
                guiForm.Controls.Add(canvas2DGUI);
                Application.Run(guiForm);
            }

            return canvasImageWrapper.getProcessedImages(input);
        }

        public void SetCursor(Cursor cursor)
        {
            canvas2DGUI.Cursor = cursor;
        }

        public void Crop(Rectangle regionOfInterest)
        {
            Point scaledLocation = new Point((int)(regionOfInterest.X / canvasImageWrapper.ScalingFactor), (int)(regionOfInterest.Y / canvasImageWrapper.ScalingFactor));
            Size scaledSize = new Size((int)(regionOfInterest.Width / canvasImageWrapper.ScalingFactor), (int)(regionOfInterest.Height / canvasImageWrapper.ScalingFactor));
            Rectangle scaledRegionOfInterest = new Rectangle(scaledLocation, scaledSize);
            canvasImageWrapper.ExecuteCommand(new CropCommand(scaledRegionOfInterest));
        }

        /* Image Event Handler Part */
        public void ImageMouseDown(object sender, MouseEventArgs e)
        {
            roiState.MouseDown(sender, e);
        }
        
        public void ImageMouseUp(object sender, MouseEventArgs e)
        {
            roiState.MouseUp(sender, e);
        }
        
        public void ImageMouseMoved(object sender, MouseEventArgs e)
        {
            roiState.MouseMoved(sender, e);
        }

        public void ImagePainted(object sender, PaintEventArgs e)
        {
            roiState.ImagePainted(sender, e);
        }

        public void SetROIState(Canvas2DROIState state)
        {
            this.roiState = state;
            canvasImageWrapper.ActiveImage.RegionOfInterest = state.ROIRect;
            RefreshCanvas();
        }

        public void RefreshCanvas()
        {
            canvas2DGUI.Refresh();
        }

        /* canvas image wrapper observer part */
        public void Notify()
        {
            Point newMarkStart = new Point((int)(canvasImageWrapper.ActiveImage.RegionOfInterest.X * canvasImageWrapper.ScalingFactor), (int)(canvasImageWrapper.ActiveImage.RegionOfInterest.Y * canvasImageWrapper.ScalingFactor));
            Point newMarkEnd = new Point((int)((canvasImageWrapper.ActiveImage.RegionOfInterest.X + canvasImageWrapper.ActiveImage.RegionOfInterest.Width) * canvasImageWrapper.ScalingFactor), (int)((canvasImageWrapper.ActiveImage.RegionOfInterest.Y + canvasImageWrapper.ActiveImage.RegionOfInterest.Height) * canvasImageWrapper.ScalingFactor));
            roiState.ROIRect = new Rectangle(newMarkStart, new Size(newMarkEnd.X - newMarkStart.X, newMarkEnd.Y - newMarkStart.Y));
        }
    }
}
